import send_msg from '@feidao-factory/send-msg';
import config from '@feidao-factory/send-msg/nodejs/config';
import check from './_check_undefined';

const DBACC_FIND = 'dbacc.find.intranet';

interface IQueryParam {
	criteria: object;
	fields: { [field_name: string]: 1 | -1 };
	page_no: number;
	page_size: number;
	query_mode: 1;
	sort: {};
	spaceid: string;
	sql: string;
	systemid: string;
	tablename: string;
}

interface IQueryResult {
	query_mode: 1;
	spaceid: string;
	systemid: string;
	tablename: string;
	dataArray: any[];
}

const spaceid = config.spaceid;

/**
 * 查询数据服务
 * @param action_id 系统参数action_id
 * @param session_id 系统参数sessionid
 * @param systemid 项目的systemid
 */
export default function query(action_id: string, session_id: string, systemid: string) {
	let params = [] as IQueryParam[];

	function prepare(tablename: string, fields: string[], filter: object, page_size: number, page_no: number, asc: string[], desc: string[]) {
		if (page_size <= 0) {
			throw new Error(`Page size[${page_size}] must greater than 1.`);
		}
		check(filter);
		const sort = asc.map((field) => {
			return { [field]: 1 };
		}).concat(desc.map((field) => {
			return { [field]: -1 };
		})).reduce((pre, cur) => {
			return { ...pre, ...cur };
		}, {});
		Object.keys(filter).map((item) => {
			if (filter[item] instanceof RegExp) {
				let reg_exp = filter[item].source;
				if (reg_exp.substr(0, 1) !== '^') {
					reg_exp = '^' + reg_exp;
				}
				if (reg_exp.substr(reg_exp.length - 1, 1) !== '$') {
					reg_exp = reg_exp + '$';
				}
				filter[item] = {
					$options: filter[item].flags,
					$regex: reg_exp
				};
			}
		});
		params.push({
			criteria: filter,
			fields: fields.reduce((pre, cur) => {
				pre[cur] = 1;
				return pre;
			}, {}),
			page_no,
			page_size,
			query_mode: 1,
			sort,
			spaceid,
			sql: '',
			systemid,
			tablename
		} as IQueryParam);
	}

	async function exec<T1, T2={}, T3={}, T4={}, T5={}, T6={}, T7={}, T8={}, T9={}, T10={}, T11={}, T12={}, T13={}, T14={}, T15={}, T16={}, T17={}, T18={}, T19={}, T20={}>() {
		const data = await (send_msg(action_id, session_id, DBACC_FIND, params) as Promise<IQueryResult[]>);
		params = [];
		return data.map((d) => {
			return d.dataArray;
		}) as [T1[], T2[], T3[], T4[], T5[], T6[], T7[], T8[], T9[], T10[], T11[], T12[], T13[], T14[], T15[], T16[], T17[], T18[], T19[], T20[]];
	}

	return {
		exec,
		prepare
	};
}
